home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / BKISSSRC.ZIP / MISC.!!! / JLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-16  |  27.0 KB  |  744 lines

  1. /****************/
  2. /*** includes ***/
  3. /****************/
  4. #include <stdio.h>
  5. #include <dir.h>
  6. #include <dos.h>
  7. #include <io.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <conio.h>
  11. #include <ctype.h>
  12.  
  13.  
  14. #define MAJORVER 1              /* \ version 1.3 */
  15. #define MINORVER 3              /* /             */
  16. #define PROGRAM_VERSION "1.3a"  /* version of library manager */
  17. #define BUFFER_SIZE 4096        /* this defines the temporary buffer size */
  18. #define MAXFILES 200            /* maximum number of files in library */
  19. #define TRUE 1
  20. #define FALSE 0
  21.  
  22.  
  23. /******************************************/
  24. /*** macros for defining error messages ***/
  25. /******************************************/
  26. #define ERR_OPEN 1
  27. #define ERR_TEMP 2
  28. #define ERR_LIB_OPEN 3
  29. #define ERR_LIB_BAD 4
  30. #define ERR_LIB_VER 5
  31. #define ERR_NOMEM 6
  32. #define ERR_TOOMANYFILES 7
  33. #define ERR_NOJUNK 8
  34.  
  35.  
  36. /*************************************/
  37. /*** values for modes of operation ***/
  38. /*************************************/
  39. #define UNKNOWN -1
  40. #define LIST_FILES 1
  41. #define DIAGNOSTICS 2
  42. #define ADD_FILE 3
  43. #define SUB_FILE 4
  44. #define EXTRACT_FILE 5
  45. #define REMOVE_JUNK 6
  46.  
  47.  
  48. /**********************************************/
  49. /*** macros for decoding of file attributes ***/
  50. /**********************************************/
  51. #define ATTR_ARCHIVE(i) (i & 32 ? 'A' : '-')
  52. #define ATTR_READONLY(i) (i & 1 ? 'R' : '-')
  53. #define ATTR_HIDDEN(i) (i & 2 ? 'H' : '-')
  54. #define ATTR_SYSTEM(i) (i & 4 ? 'S' : '-')
  55.  
  56.  
  57. /******************/
  58. /*** structures ***/
  59. /******************/
  60. struct header_type {
  61.     char signature[4];
  62.     char majorver, minorver;
  63.     unsigned numfiles;
  64.     unsigned long diroffset;
  65. } JLIB_header;
  66. struct file_info {
  67.     char fileattr;
  68.     struct ftime timedate;
  69.     unsigned long filesize;
  70.     char filename[13];
  71.     unsigned long fileoffset;
  72. } JLIB_directory[MAXFILES];
  73.  
  74.  
  75. /*****************/
  76. /*** variables ***/
  77. /*****************/
  78. int mode = UNKNOWN, quietmode = FALSE, swapthem = FALSE;
  79. char *buffer;
  80. char TempName[13] = {"$$JLIB$$.TMP"}, LibName[80], filename[80];
  81. FILE *LibFP, *TempFP;
  82. struct ffblk findfirstblock;
  83. int nextfile, lastfile, getnew, curpos;
  84. unsigned long HeaderOffset;
  85.  
  86.  
  87. /******************/
  88. /*** prototypes ***/
  89. /******************/
  90. void list_files(void);
  91. void diagnostics(void);
  92. void add_file(char *filename);
  93. void sub_file(char *filename);
  94. void extract_file(char *filename);
  95. void remove_junk(void);
  96. char *fixfilename (char *filename);
  97. char *shortname (char *filename);
  98. char *pathpart (char *filename);
  99. int get_next_external_name(void);
  100. int get_next_internal_name(void);
  101. void handle_error(int errortype);
  102.  
  103. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  104. void main(void)
  105. {
  106.     /******************************/
  107.     /*** print out our greeting ***/
  108.     /******************************/
  109.     printf("JLIB.EXE -- JLib File Manager, v%s\n", PROGRAM_VERSION);
  110.     printf("by  _______  /\n");
  111.     printf("       /    /      ┌──┌┐  │─┬─┌──┌─┐┌─┐┌─┐o┌──┌──┌──\n");
  112.     printf("      /    /       ├─ │└─┐│ │ ├─ ├┬┘├─┘├┬┘│└─┐├─ └─┐\n");
  113.     printf("/____/    /_____   └──│  └┘ │ └──│ \\│  │ \\│──┘└────┘\n\n");
  114.  
  115.  
  116.     /*****************************************/
  117.     /*** determine which mode is requested ***/
  118.     /*****************************************/
  119.     if      (_argc >= 3 && strcmp(strupr(_argv[1]), "/V") == 0) mode = LIST_FILES;
  120.     else if (_argc >= 3 && strcmp(strupr(_argv[1]), "/T") == 0) mode = DIAGNOSTICS;
  121.     else if (_argc >= 4 && strcmp(strupr(_argv[1]), "/A") == 0) mode = ADD_FILE;
  122.     else if (_argc >= 4 && strcmp(strupr(_argv[1]), "/D") == 0) mode = SUB_FILE;
  123.     else if (_argc >= 4 && strcmp(strupr(_argv[1]), "/E") == 0) mode = EXTRACT_FILE;
  124.     else if (_argc >= 3 && strcmp(strupr(_argv[1]), "/R") == 0) mode = REMOVE_JUNK;
  125.     if (_argc >= 3) {
  126.         strncpy(LibName, strupr(_argv[2]), 75);
  127.         if (strchr(shortname(LibName), '.') == NULL) strcat(LibName, ".JLB");
  128.     }
  129.     if (_argc >= 4) {
  130.         nextfile = 3; lastfile = _argc;
  131.     } else {
  132.         nextfile = lastfile = 0;
  133.     }
  134.     getnew = TRUE; curpos = 0;
  135.  
  136.  
  137.     /*******************************/
  138.     /*** display help, if needed ***/
  139.     /*******************************/
  140.     if (mode == UNKNOWN) {
  141.         printf("syntax:  JLIB /V «library.JLB»                  (to view contents)\n");
  142.         printf("         JLIB /T «library.JLB»                  (run diagnostics)\n");
  143.         printf("         JLIB /A «library.JLB» «filename.EXT»   (to add a file)\n");
  144.         printf("         JLIB /D «library.JLB» «filename.EXT»   (to delete file)\n");
  145.         printf("         JLIB /E «library.JLB» «filename.EXT»   (to extract file)\n");
  146.         printf("         JLIB /R «library.JLB»                  (remove junk data)\n");
  147.         exit(1);
  148.     }
  149.  
  150.  
  151.     /*****************************************************/
  152.     /*** open the library and read the file informaion ***/
  153.     /*****************************************************/
  154.     printf("Opening %.12s...", fixfilename(LibName));
  155.     if ((LibFP = fopen(LibName, "rb")) != NULL) {
  156.         int i;
  157.  
  158.         fseek(LibFP, -1L * sizeof(HeaderOffset), SEEK_END);
  159.         fread(&HeaderOffset, sizeof(HeaderOffset), 1, LibFP);
  160.         HeaderOffset = filelength(fileno(LibFP)) - HeaderOffset;
  161.         fseek(LibFP, HeaderOffset, SEEK_SET);
  162.         fread(&JLIB_header, sizeof(struct header_type), 1, LibFP);
  163.         if (strncmp(JLIB_header.signature, "JLib", 4) != 0) handle_error(ERR_LIB_BAD);
  164.         if (JLIB_header.majorver != MAJORVER || JLIB_header.minorver != MINORVER) handle_error(ERR_LIB_VER);
  165.         fseek(LibFP, HeaderOffset + JLIB_header.diroffset, SEEK_SET);
  166.         for (i = 0; i < JLIB_header.numfiles; i++) {
  167.             fread(&JLIB_directory[i], sizeof(struct file_info), 1, LibFP);
  168.         }
  169.     } else if (mode == ADD_FILE) {
  170.         HeaderOffset = 0;
  171.         if ((LibFP = fopen(LibName, "w+b")) == NULL) handle_error(ERR_LIB_OPEN);
  172.         strncpy(JLIB_header.signature, "JLib", 4);
  173.         JLIB_header.majorver = MAJORVER;
  174.         JLIB_header.minorver = MINORVER;
  175.         JLIB_header.numfiles = 0;
  176.         JLIB_header.diroffset = sizeof(struct header_type);
  177.         fwrite(&JLIB_header, sizeof(struct header_type), 1, LibFP);
  178.     } else {
  179.         printf("\n");
  180.         handle_error(ERR_LIB_OPEN);
  181.     }
  182.     printf("\n");
  183.  
  184.  
  185.     /*************************************************************/
  186.     /*** make a temporary file if we're going to modify things ***/
  187.     /*************************************************************/
  188.     if (mode == ADD_FILE || mode == SUB_FILE) {
  189.         unsigned long copysize, blocksize;
  190.  
  191.         copysize = filelength(fileno(LibFP));
  192.         fseek(LibFP, 0, SEEK_SET);
  193.         if ((TempFP = fopen(TempName, "w+b")) == NULL) handle_error(ERR_TEMP);
  194.         if ((buffer = malloc(BUFFER_SIZE)) == NULL) handle_error(ERR_NOMEM);
  195.  
  196.         while (copysize) {
  197.             blocksize = (copysize > BUFFER_SIZE ? BUFFER_SIZE : copysize);
  198.             fread(buffer, sizeof(char), blocksize, LibFP);
  199.             fwrite(buffer, sizeof(char), blocksize, TempFP);
  200.             copysize -= blocksize;
  201.         }
  202.  
  203.         free(buffer);
  204.     }
  205.  
  206.  
  207.     /*************************************************************/
  208.     /*** dispatch to the correct code for the specified action ***/
  209.     /*************************************************************/
  210.     switch (mode) {
  211.         case LIST_FILES:
  212.             list_files();
  213.             break;
  214.         case DIAGNOSTICS:
  215.             diagnostics();
  216.             break;
  217.         case ADD_FILE:
  218.             swapthem = TRUE;
  219.             while (get_next_external_name()) add_file(filename);
  220.             break;
  221.         case SUB_FILE:
  222.             swapthem = TRUE;
  223.             while (get_next_internal_name()) {sub_file(filename); curpos--;}
  224.             break;
  225.         case EXTRACT_FILE:
  226.             while (get_next_internal_name()) extract_file(filename);
  227.             break;
  228.         case REMOVE_JUNK:
  229.             remove_junk();
  230.             break;
  231.         default: break;
  232.     }
  233.  
  234.  
  235.     /*************************/
  236.     /*** close the library ***/
  237.     /*************************/
  238.     fcloseall();
  239.     if (swapthem) {
  240.         unlink(LibName);
  241.         rename(TempName, LibName);
  242.     } else {
  243.         unlink(TempName);
  244.     }
  245.  
  246.  
  247.     /*****************************/
  248.     /*** terminate the program ***/
  249.     /*****************************/
  250.     exit(0);
  251. }
  252. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  253. void list_files(void)
  254. {
  255.     unsigned i, linecount = 9;
  256.     unsigned long totalsize; 
  257.  
  258.     printf("Filename     Size       Date       Time     Attr Offset     End\n");
  259.     printf("════════════ ══════════ ══════════ ════════ ════ ══════════ ══════════\n");
  260.     for (i = 0; i < JLIB_header.numfiles; i++, linecount++) {
  261.         printf("%-12.12s %10lu %02.2i-%02.2i-%04.4i %02.2i:%02.2i:%02.2i %c%c%c%c %10lu %10lu\n",
  262.             JLIB_directory[i].filename, JLIB_directory[i].filesize, JLIB_directory[i].timedate.ft_month,
  263.             JLIB_directory[i].timedate.ft_day, JLIB_directory[i].timedate.ft_year + 1980,
  264.             JLIB_directory[i].timedate.ft_hour, JLIB_directory[i].timedate.ft_min,
  265.             JLIB_directory[i].timedate.ft_tsec * 2, ATTR_ARCHIVE(JLIB_directory[i].fileattr),
  266.             ATTR_READONLY(JLIB_directory[i].fileattr), ATTR_HIDDEN(JLIB_directory[i].fileattr),
  267.             ATTR_SYSTEM(JLIB_directory[i].fileattr), JLIB_directory[i].fileoffset,
  268.             JLIB_directory[i].fileoffset+JLIB_directory[i].filesize-1);
  269.         if (linecount % 22 == 0) {
  270.             printf("\nPress any key to continue listing...");
  271.             if (!getch()) getch();
  272.             printf("\n");
  273.         }
  274.     }
  275.     printf("════════════ ══════════ ══════════ ════════ ════ ══════════ ══════════\n");
  276.     if (JLIB_header.numfiles == 0) {
  277.         totalsize = 0;
  278.     } else {
  279.         totalsize = JLIB_directory[JLIB_header.numfiles-1].fileoffset + \
  280.             JLIB_directory[JLIB_header.numfiles-1].filesize - JLIB_header.numfiles * \
  281.             sizeof(struct file_info) - sizeof(struct header_type);
  282.     }
  283.     printf("%12u %10lu\n", JLIB_header.numfiles, totalsize);
  284. }
  285. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  286. void diagnostics(void)
  287. {
  288.     char buffer[6];
  289.     unsigned i, errorsfound = 0;
  290.     unsigned long reallength, datalength, lastbyte;
  291.  
  292.  
  293.     printf("There are %lu bytes stored before start of library.\n", HeaderOffset);
  294.     lastbyte = sizeof(struct header_type) - 1;
  295.     datalength = sizeof(struct header_type) + JLIB_header.numfiles * sizeof(struct file_info);
  296.     for (i = 0; i < JLIB_header.numfiles; i++) {
  297.         if (lastbyte + 1 != JLIB_directory[i].fileoffset) {
  298.             printf("Gap in data between file \"%.12s\" and previous data\n", JLIB_directory[i].filename);
  299.             errorsfound++;
  300.         }
  301.         lastbyte = JLIB_directory[i].fileoffset + JLIB_directory[i].filesize - 1;
  302.         datalength += JLIB_directory[i].filesize;
  303.     }
  304.     datalength += sizeof(HeaderOffset);
  305.     if (lastbyte + 1 != JLIB_header.diroffset) {
  306.         printf("Gap in data between last file and directory information\n");
  307.         errorsfound++;
  308.     }
  309.     reallength = filelength(fileno(LibFP)) - HeaderOffset;
  310.     if (datalength < reallength) {
  311.         printf("Library is %lu bytes longer than expected.\n", reallength - datalength);
  312.         errorsfound++;
  313.     } else if (datalength > reallength) {
  314.         printf("Library is %lu bytes shorter than expected.\n", datalength - reallength);
  315.         errorsfound++;
  316.     }
  317.     printf("%s error%s detected.\n", (errorsfound ? itoa(errorsfound, \
  318.             buffer, 10) : "No"), (errorsfound != 1 ? "s" : ""));
  319. }
  320. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  321. void add_file(char *filename)
  322. {
  323.     FILE *FP;
  324.     unsigned i;
  325.     char *buffer;
  326.     unsigned long copysize, blocksize, ourlength;
  327.  
  328.  
  329.     /***********************************************/
  330.     /*** if the file is already there, update it ***/
  331.     /***********************************************/
  332.     for (i = 0; i < JLIB_header.numfiles; i++) {
  333.         if (strncmp(JLIB_directory[i].filename, fixfilename(filename), 13) == 0) {
  334.             printf("updating %s...", fixfilename(filename));
  335.             quietmode = TRUE;
  336.             sub_file(filename);
  337.             add_file(filename);
  338.             quietmode = FALSE;
  339.             printf("done\n");
  340.             return;
  341.         }
  342.     }
  343.  
  344.  
  345.     /************************/
  346.     /*** open up the file ***/
  347.     /************************/
  348.     if (!quietmode) printf("adding %s...", fixfilename(filename));
  349.     if ((FP = fopen(filename, "rb")) == NULL) {
  350.         printf("Error opening file\n", filename);
  351.         return;
  352.     }
  353.  
  354.  
  355.     /*******************************************/
  356.     /*** set up a structure for the new file ***/
  357.     /*******************************************/
  358.     i = JLIB_header.numfiles;
  359.     JLIB_header.numfiles++;
  360.     if (JLIB_header.numfiles > MAXFILES) handle_error(ERR_TOOMANYFILES);
  361.     strncpy(JLIB_directory[i].filename, fixfilename(filename), 12);
  362.     JLIB_directory[i].filesize = filelength(fileno(FP));
  363.     JLIB_directory[i].fileattr = 0;
  364.     getftime(fileno(FP), &JLIB_directory[i].timedate);
  365.     if (i != 0) {
  366.         JLIB_directory[i].fileoffset = JLIB_directory[i-1].fileoffset + JLIB_directory[i-1].filesize;
  367.     } else {
  368.         JLIB_directory[i].fileoffset = sizeof(struct header_type);
  369.     }
  370.     JLIB_header.diroffset += JLIB_directory[i].filesize;
  371.  
  372.  
  373.     /******************************/
  374.     /*** write out a new header ***/
  375.     /******************************/
  376.     fseek(TempFP, HeaderOffset, SEEK_SET);
  377.     fwrite(&JLIB_header, sizeof(struct header_type), 1, TempFP);
  378.  
  379.  
  380.     /*********************************************/
  381.     /*** copy over the data of the file to add ***/
  382.     /*********************************************/
  383.     if ((buffer = malloc(BUFFER_SIZE)) == NULL) handle_error(ERR_NOMEM);
  384.     fseek(TempFP, HeaderOffset+JLIB_directory[i].fileoffset, SEEK_SET);
  385.     copysize = filelength(fileno(FP));
  386.     fseek(FP, 0, SEEK_SET);
  387.     while (copysize) {
  388.         blocksize = (copysize > BUFFER_SIZE ? BUFFER_SIZE : copysize);
  389.         fread(buffer, sizeof(char), blocksize, FP);
  390.         fwrite(buffer, sizeof(char), blocksize, TempFP);
  391.         copysize -= blocksize;
  392.         if (!quietmode) printf(".");
  393.     }
  394.     free(buffer);
  395.  
  396.  
  397.     /**********************************************/
  398.     /*** write out the new directory structures ***/
  399.     /**********************************************/
  400.     fseek(TempFP, HeaderOffset+JLIB_header.diroffset, SEEK_SET);
  401.     fwrite(JLIB_directory, sizeof(struct file_info), JLIB_header.numfiles, TempFP);
  402.  
  403.     
  404.     /****************************************/
  405.     /*** write out our pointer at the end ***/
  406.     /****************************************/
  407.     fseek(TempFP, HeaderOffset+JLIB_header.diroffset + JLIB_header.numfiles * \
  408.             sizeof(struct file_info), SEEK_SET);
  409.     ourlength = sizeof(ourlength) + ftell(TempFP) - HeaderOffset;
  410.     fwrite(&ourlength, sizeof(ourlength), 1, TempFP);
  411.     chsize(fileno(TempFP), ourlength + HeaderOffset);
  412.  
  413.     fclose(FP);
  414.     if (!quietmode) printf("done\n");
  415. }
  416. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  417. void sub_file(char *filename)
  418. {
  419.     char *buffer;
  420.     unsigned i, entrynumber, found = FALSE;
  421.     unsigned long copysize, blocksize, sourcepos, targetpos, filesize, ourlength;
  422.  
  423.  
  424.     /********************************************/
  425.     /*** check to see if the file is in there ***/
  426.     /********************************************/
  427.     if (!quietmode) printf("deleting %s...", fixfilename(filename));
  428.     for (i = 0; i < JLIB_header.numfiles; i++) {
  429.         if (strncmp(JLIB_directory[i].filename, fixfilename(filename), 13) == 0) {
  430.             found = TRUE;
  431.             entrynumber = i;
  432.             break;
  433.         }
  434.     }
  435.     if (!found) {
  436.         printf("Error--file not in library\n");
  437.         return;
  438.     }
  439.  
  440.  
  441.     /******************************/
  442.     /*** write out a new header ***/
  443.     /******************************/
  444.     JLIB_header.numfiles--;
  445.     JLIB_header.diroffset -= JLIB_directory[entrynumber].filesize;
  446.     fseek(TempFP, HeaderOffset, SEEK_SET);
  447.     fwrite(&JLIB_header, sizeof(char), sizeof(struct header_type), TempFP);
  448.     JLIB_header.numfiles++;     /* just for now (we'll fix it later) */
  449.  
  450.  
  451.     /*************************************************************/
  452.     /*** figure out how much data after the file must be moved ***/
  453.     /*************************************************************/
  454.     copysize = 0;
  455.     for (i = entrynumber + 1; i < JLIB_header.numfiles; i++) {
  456.         copysize += JLIB_directory[i].filesize;
  457.     }
  458.     sourcepos = HeaderOffset + JLIB_directory[entrynumber+1].fileoffset;
  459.     targetpos = HeaderOffset + JLIB_directory[entrynumber].fileoffset;
  460.  
  461.  
  462.     /********************************************/
  463.     /*** move the data after the file forward ***/
  464.     /********************************************/
  465.     if ((buffer = malloc(BUFFER_SIZE)) == NULL) handle_error(ERR_NOMEM);
  466.     while (copysize) {
  467.         blocksize = (copysize > BUFFER_SIZE ? BUFFER_SIZE : copysize);
  468.         fseek(TempFP, sourcepos, SEEK_SET);
  469.         fread(buffer, sizeof(char), blocksize, TempFP);
  470.         fseek(TempFP, targetpos, SEEK_SET);
  471.         fwrite(buffer, sizeof(char), blocksize, TempFP);
  472.         copysize -= blocksize;
  473.         sourcepos += blocksize;
  474.         targetpos += blocksize;
  475.         if (!quietmode) printf(".");
  476.     }
  477.     free(buffer);
  478.  
  479.  
  480.     /*************************************************************/
  481.     /*** update our directory structures to reflect the change ***/
  482.     /*************************************************************/
  483.     filesize = JLIB_directory[entrynumber].filesize;
  484.     for (i = entrynumber + 1; i < JLIB_header.numfiles; i++) {
  485.         JLIB_directory[i - 1] = JLIB_directory[i];
  486.         JLIB_directory[i - 1].fileoffset -= filesize;
  487.     }
  488.     JLIB_header.numfiles--;     /* told 'ya I'd change it back */
  489.  
  490.  
  491.     /**********************************************/
  492.     /*** write out the new directory structures ***/
  493.     /**********************************************/
  494.     fseek(TempFP, HeaderOffset + JLIB_header.diroffset, SEEK_SET);
  495.     fwrite(JLIB_directory, sizeof(struct file_info), JLIB_header.numfiles, TempFP);
  496.  
  497.  
  498.     /********************************************************************/
  499.     /*** write out our pointer at the end and chop off any extra data ***/
  500.     /********************************************************************/
  501.     fseek(TempFP, HeaderOffset+JLIB_header.diroffset + JLIB_header.numfiles * \
  502.             sizeof(struct file_info), SEEK_SET);
  503.     ourlength = sizeof(ourlength) + ftell(TempFP) - HeaderOffset;
  504.     fwrite(&ourlength, sizeof(ourlength), 1, TempFP);
  505.     chsize(fileno(TempFP), ourlength + HeaderOffset);
  506.  
  507.     if (!quietmode) printf("done\n");
  508. }
  509. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  510. void extract_file(char *filename)
  511. {
  512.     unsigned i, entrynumber, found = FALSE;
  513.     char *buffer;
  514.     FILE *FP;
  515.     unsigned long copysize, blocksize;
  516.  
  517.  
  518.     /********************************************/
  519.     /*** check to see if the file is in there ***/
  520.     /********************************************/
  521.     if (!quietmode) printf("extracting %s...", fixfilename(filename));
  522.     for (i = 0; i < JLIB_header.numfiles; i++) {
  523.         if (strncmp(JLIB_directory[i].filename, fixfilename(filename), 13) == 0) {
  524.             found = TRUE;
  525.             entrynumber = i;
  526.             break;
  527.         }
  528.     }
  529.     if (!found) {
  530.         printf("Error--file not in library\n");
  531.         return;
  532.     }
  533.  
  534.  
  535.     /******************************************************/
  536.     /*** open up the output file and write out the data ***/
  537.     /******************************************************/
  538.     if ((buffer = malloc(BUFFER_SIZE)) == NULL) handle_error(ERR_NOMEM);
  539.     if ((FP = fopen(filename, "w+b")) == NULL) {
  540.         printf("Error opening output file.\n");
  541.         return;
  542.     }
  543.     fseek(LibFP, HeaderOffset + JLIB_directory[entrynumber].fileoffset, SEEK_SET);
  544.     copysize = JLIB_directory[entrynumber].filesize;
  545.     while (copysize) {
  546.         blocksize = (copysize > BUFFER_SIZE ? BUFFER_SIZE : copysize);
  547.         fread(buffer, sizeof(char), blocksize, LibFP);
  548.         fwrite(buffer, sizeof(char), blocksize, FP);
  549.         copysize -= blocksize;
  550.         if (!quietmode) printf(".");
  551.     }
  552.     fclose(FP);
  553.     free(buffer);
  554.     if (!quietmode) printf("done\n");
  555. }
  556. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  557. void remove_junk(void)
  558. {
  559.     char *buffer;
  560.     unsigned long copysize, blocksize;
  561.  
  562.     if (HeaderOffset == 0) handle_error(ERR_NOJUNK);
  563.     if ((buffer = malloc(BUFFER_SIZE)) == NULL) handle_error(ERR_NOMEM);
  564.     if ((TempFP = fopen(TempName, "w+b")) == NULL) handle_error(ERR_TEMP);
  565.     printf("removing %lu bytes of junk data...", HeaderOffset);
  566.     fseek(LibFP, HeaderOffset, SEEK_SET);
  567.     copysize = filelength(fileno(LibFP)) - HeaderOffset;
  568.     while (copysize) {
  569.         blocksize = (copysize > BUFFER_SIZE ? BUFFER_SIZE : copysize);
  570.         fread(buffer, sizeof(char), blocksize, LibFP);
  571.         fwrite(buffer, sizeof(char), blocksize, TempFP);
  572.         copysize -= blocksize;
  573.         printf(".");
  574.     }
  575.     fclose(LibFP); fclose(TempFP);
  576.     unlink(LibName);
  577.     rename(TempName, LibName);
  578.     free(buffer);
  579.     printf("\n");
  580. }
  581. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  582. char *fixfilename (char *filename)
  583. {
  584.     int i, j;
  585.     char *p, buffer[80];
  586.  
  587.     // chop off the drive or path
  588.     if ((p = strrchr(filename, '\\')) != NULL) {
  589.         strncpy(buffer, strupr(p + 1), 80);
  590.     } else if ((p = strrchr(filename, ':')) != NULL) {
  591.         strncpy(buffer, strupr(p + 1), 80);
  592.     } else {
  593.         strncpy(buffer, strupr(filename), 80);
  594.     }
  595.  
  596.     // remove any extra letters after astericks
  597.     for (i = 0; i < strlen(buffer); i++) {
  598.         if (buffer[i] == '*') {
  599.             for (j = i + 1; j < strlen(buffer); j++) {
  600.                 if (buffer[j] == '.' || buffer[j] == 0) break;
  601.             }
  602.             if (j > i + 1) strcpy(&buffer[i+1], &buffer[j]);
  603.         }
  604.     }
  605.  
  606.     // make sure there's a period in it
  607.     if ((p = strrchr(buffer, '.')) == NULL) {
  608.         j = '.'; strcat(buffer, (char *) &j);
  609.     }
  610.  
  611.     // limit the length of the filename to 8.3
  612.     for (i = 0, j = 0; i < strlen(buffer); i++, j++) {
  613.         if (buffer[i] == '.') {
  614.             if (j > 8) strcpy(&buffer[8], &buffer[i]);
  615.             break;
  616.         }
  617.     }
  618.     *(strchr(buffer, '.')+4) = 0;
  619.  
  620.     return(buffer);
  621. }
  622. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  623. char *shortname (char *filename)
  624. {
  625.     char *p;
  626.  
  627.     if ((p = strrchr(filename, '\\')) != NULL) {
  628.         return(strupr(p + 1));
  629.     } else if ((p = strrchr(filename, ':')) != NULL) {
  630.         return(strupr(p + 1));
  631.     } else {
  632.         return(strupr(filename));
  633.     }
  634. }
  635. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  636. char *pathpart (char *filename)
  637. {
  638.     char *p;
  639.     char buffer[80];
  640.  
  641.     strncpy(buffer, filename, 80);
  642.     if ((p = strrchr(buffer, '\\')) != NULL) {
  643.         *(p+1) = 0;
  644.     } else if ((p = strrchr(filename, ':')) != NULL) {
  645.         *(p+1) = 0;
  646.     } else {
  647.         buffer[0] = 0;
  648.     }
  649.     return(buffer);
  650. }
  651. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  652. int get_next_external_name(void)
  653. {
  654.     int done;
  655.  
  656.     while (TRUE) {
  657.         if (getnew) {
  658.             if (nextfile >= lastfile) return(FALSE);
  659.             done = findfirst(_argv[nextfile], &findfirstblock, 0);
  660.             getnew = FALSE;
  661.         } else {
  662.             done = findnext(&findfirstblock);
  663.         }
  664.         if (done) {
  665.             nextfile++;
  666.             getnew = TRUE;
  667.         } else {
  668.             strcpy(filename, pathpart(_argv[nextfile]));
  669.             strcat(filename, findfirstblock.ff_name);
  670.             if (strncmp(filename, fixfilename(LibName), 13) != 0 &&
  671.                 strncmp(filename, TempName, 13) != 0) return(TRUE);
  672.         }
  673.     }
  674. }
  675. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  676. int get_next_internal_name(void)
  677. {
  678.     int match, i, pointer1, pointer2;
  679.     char wildcard[13];
  680.  
  681.     while (TRUE) {
  682.         if (nextfile >= lastfile) return(FALSE);
  683.         for (; curpos < JLIB_header.numfiles; curpos++) {
  684.             strcpy(wildcard, fixfilename(_argv[nextfile]));
  685.             pointer1 = pointer2 = 0; match = UNKNOWN;
  686.             while (match == UNKNOWN && pointer1 <= strlen(wildcard) && \
  687.                     pointer2 <= strlen(JLIB_directory[curpos].filename)) {
  688.                 switch (wildcard[pointer1]) {
  689.                     case 0:
  690.                         if (JLIB_directory[curpos].filename[pointer2] == 0) {
  691.                             match = TRUE;
  692.                         } else {
  693.                             match = FALSE;
  694.                         }
  695.                         break;
  696.                     case '*':
  697.                         if (JLIB_directory[curpos].filename[pointer2] == '.' ||
  698.                                 JLIB_directory[curpos].filename[pointer2] == 0) {
  699.                             pointer1++;
  700.                         } else {
  701.                             pointer2++;
  702.                         }
  703.                         break;
  704.                     case '?':
  705.                         pointer1++; pointer2++;
  706.                         break;
  707.                     default:
  708.                         if (wildcard[pointer1] != JLIB_directory[curpos].filename[pointer2]) {
  709.                             match = FALSE;
  710.                         } else {
  711.                             pointer1++; pointer2++;
  712.                         }
  713.                         break;
  714.                 }
  715.             }
  716.             if (match == TRUE) {
  717.                 strcpy(filename, JLIB_directory[curpos].filename);
  718.                 curpos++;
  719.                 return(TRUE);
  720.             }
  721.         }
  722.         nextfile++; curpos = 0;
  723.     }
  724. }
  725. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  726. void handle_error(int errortype)
  727. {
  728.     fcloseall();
  729.     printf("***Error*** ");
  730.     switch (errortype) {
  731.         case ERR_OPEN: printf("Cannot open file\n"); break;
  732.         case ERR_TEMP: printf("Cannot create temporary file\n"); break;
  733.         case ERR_LIB_OPEN: printf("Cannot open library\n"); break;
  734.         case ERR_LIB_BAD: printf("Bad or corrupted library file\n"); break;
  735.         case ERR_LIB_VER: printf("Unknown library version\n"); break;
  736.         case ERR_NOMEM: printf("Insufficient memory\n"); break;
  737.         case ERR_TOOMANYFILES: printf("Too many files in library\n"); break;
  738.         case ERR_NOJUNK: printf("No junk data to remove\n"); break;
  739.         default: printf("Unknown error\n"); break;
  740.     }
  741.     exit(errortype);
  742. }
  743. //░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  744.